package com.inspur.edp.paasuser.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.inspur.edp.common.ApiEnum;
import com.inspur.edp.common.CommonUtils;
import com.inspur.edp.common.paasexception.ErrorCodes;
import com.inspur.edp.common.paasexception.PaasException;
import com.inspur.edp.nexus.dao.GetNexusUserPaaswordRelationDao;
import com.inspur.edp.nexus.domain.GetNexusUserPasswordRelation;
import com.inspur.edp.paasuser.SynchronizationInfoService;
import com.inspur.edp.paasuser.dao.GspDevEnvMapDao;
import com.inspur.edp.paasuser.dao.GspDevTeamEnvRelationDao;
import com.inspur.edp.paasuser.dao.GspPaasEnvFlagDao;
import com.inspur.edp.paasuser.dao.SynchronizationInfoDao;
import com.inspur.edp.paasuser.domain.GspDevEnvMap;
import com.inspur.edp.paasuser.domain.GspDevTeamEnvRelation;
import com.inspur.edp.paasuser.domain.GspPaasEnvFlag;
import com.inspur.edp.paasuser.domain.GspPaasUserSynch;
import com.inspur.edp.paasuser.dto.SynchqronizationInfoDto;
import com.inspur.edp.team.dao.PaasTeamMemberDao;
import com.inspur.edp.team.domain.PaasTeamMember;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.security.signature.sdk.Credentials;
import io.iec.edp.caf.security.signature.sdk.Signature;
import io.iec.edp.caf.sysmanager.api.common.AuditEntity;
import io.iec.edp.caf.sysmanager.api.common.SysAssResultPackage;
import io.iec.edp.caf.sysmanager.api.data.group.GroupEntity;
import io.iec.edp.caf.sysmanager.api.data.position.Position;
import io.iec.edp.caf.sysmanager.api.data.user.User;
import io.iec.edp.caf.sysmanager.api.data.user.UserExtend;
import io.iec.edp.caf.sysmanager.api.manager.user.UserExtendManager;
import io.iec.edp.caf.sysmanager.api.manager.user.UserManager;
import org.springframework.data.domain.Example;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

public class SynchronizationInfoServiceImpl implements SynchronizationInfoService {
    private RestTemplate restTemplate = SpringBeanUtils.getBean(RestTemplate.class);
    private UserManager userManager = SpringBeanUtils.getBean(UserManager.class);
    private UserExtendManager userExtendManager = SpringBeanUtils.getBean(UserExtendManager.class);
    private SynchronizationInfoDao synchronizationInfoDao= SpringBeanUtils.getBean(SynchronizationInfoDao.class);
    private GspDevEnvMapDao gspDevEnvMapDao =SpringBeanUtils.getBean(GspDevEnvMapDao.class);
    private GspDevTeamEnvRelationDao gspDevTeamEnvRelationDao = SpringBeanUtils.getBean(GspDevTeamEnvRelationDao.class);
    private PaasTeamMemberDao paasTeamMemberDao = SpringBeanUtils.getBean(PaasTeamMemberDao.class);
//    private GetNexusUserPaaswordRelationDao paasUserPasswordDao = SpringBeanUtils.getBean(GetNexusUserPaaswordRelationDao.class);
    private GspPaasEnvFlagDao gspPaasEnvFlagDao = SpringBeanUtils.getBean(GspPaasEnvFlagDao.class);
    @Override
    public void addUserReceive(User user) {
        String str=UUID.randomUUID().toString();
        String password="Pp!0"+str.substring(str.length()-10);

        userManager.addUserWithPwd(user,password);
    }

    @Override
    public String checkEnvironment() {
        if(gspPaasEnvFlagDao.count()>0){
            return "exsis";
        } else {
            return "noexsis";
        }
    }
    @Override
    public String saveEnvironment() {
        GspPaasEnvFlag gspPaasEnvFlag = new GspPaasEnvFlag();
        gspPaasEnvFlag.setId(UUID.randomUUID().toString());
        gspPaasEnvFlagDao.save(gspPaasEnvFlag);
        return "OK";
    }
    @Override
    public void addUser(SynchqronizationInfoDto synchqronizationInfoDto) {
        String jsonObject=getUserJsonString(synchqronizationInfoDto.getUserId());

        List<String> urls = queryTeamInfo(synchqronizationInfoDto.getTeamId());
        for(String str:urls ){
            HttpHeaders headers= generateHeader(synchqronizationInfoDto.setTargetApi(ApiEnum.ADDUSER.getName()).setTargetAddress(str));
            if(verifyUserIsAppend(synchqronizationInfoDto)){
                userSwitch(synchqronizationInfoDto.setUserSwitch(true));
                continue;
            }
            addOneUser(synchqronizationInfoDto,jsonObject,headers);
        }
    }
    @Override
    public void addTeamUser(SynchqronizationInfoDto synchqronizationInfoDto) {
        if(verifyEnvironmentIsBind(synchqronizationInfoDto)){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_CHECK_0001,synchqronizationInfoDto.getTargetAddress());
        }

        HttpHeaders headers= generateHeader(synchqronizationInfoDto.setTargetApi(ApiEnum.ADDUSER.getName()));

        PaasTeamMember paasTeamMember =new PaasTeamMember();
        paasTeamMember.setTeamId(synchqronizationInfoDto.getTeamId());
        Example<PaasTeamMember> example = Example.of(paasTeamMember);
        List<PaasTeamMember> paasTeamMemberList = paasTeamMemberDao.findAll(example);
        for(PaasTeamMember s:paasTeamMemberList){
            synchqronizationInfoDto.setUserId(s.getUserId());
            synchqronizationInfoDto.setIsAdmin(s.getRoleType()==0?false:true);
            String jsonObject=getUserJsonString(synchqronizationInfoDto.getUserId());
            addOneUser(synchqronizationInfoDto,jsonObject,headers);
        }
        saveEnvironmentIsBind(synchqronizationInfoDto);

    }

    @Override
    public void userSwitch(SynchqronizationInfoDto synchqronizationInfoDto) {

        if(synchqronizationInfoDto.getUserId()==null){
            // team untie
            teamUserSwitch(synchqronizationInfoDto);
        }else {
            // user bind and untie
            singleUserSwitch(synchqronizationInfoDto);
        }
    }
    private void teamUserSwitch(SynchqronizationInfoDto synchqronizationInfoDto){
        try{
            HttpHeaders headers= generateHeader(synchqronizationInfoDto.setTargetApi( ApiEnum.USERSSWITCH.getName()));
            HttpEntity<String> requestEntity = new HttpEntity<>(headers);
            PaasTeamMember paasTeamMember =new PaasTeamMember();
            paasTeamMember.setTeamId(synchqronizationInfoDto.getTeamId());
            Example<PaasTeamMember> example = Example.of(paasTeamMember);
            List<PaasTeamMember> paasTeamMemberList = paasTeamMemberDao.findAll(example);

            String userIdList=paasTeamMemberList.stream().map(user -> "\""+user.getUserId()+"\"").collect(Collectors.joining(","));
            String address = ApiEnum.USERSSWITCH.getApiAddress(synchqronizationInfoDto.getTargetAddress()) +
                    "?userIdList="+"[" + userIdList +"]"+
                    "&action=stop" +
                    "&isLock=false" +
                    "&state=0";
            restTemplate.put(address,requestEntity);
        } catch (Exception e){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_ERROR_0001);
        }
    }

    private void singleUserSwitch(SynchqronizationInfoDto synchqronizationInfoDto) {
        try{
            List<String> urls = queryTeamInfo(synchqronizationInfoDto.getTeamId());
            for(String str:urls ){
                HttpHeaders headers= generateHeader(synchqronizationInfoDto.setTargetApi(ApiEnum.USERSWITCH.getName()).setTargetAddress(str));
                HttpEntity<String> requestEntity = new HttpEntity<>(headers);
                String address = ApiEnum.USERSWITCH.getApiAddress(synchqronizationInfoDto.getTargetAddress()) +
                        "?userId=" + synchqronizationInfoDto.getUserId() +
                        "&action=stop" +
                        "&isLock=false" +
                        "&state="+(synchqronizationInfoDto.getUserSwitch()?1:0);
                restTemplate.put(address,requestEntity);
            }
        } catch (Exception e){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_ERROR_0002);
        }
    }

    private List<String> queryTeamInfo(String teamId){
        List<String> urls=new ArrayList<>();
        try{
            GspDevTeamEnvRelation gspDevTeamEnvRelation= new GspDevTeamEnvRelation();
            gspDevTeamEnvRelation.setTeamId(teamId);
            Example<GspDevTeamEnvRelation> example = Example.of(gspDevTeamEnvRelation);
            List<GspDevTeamEnvRelation> gspDevTeamEnvRelationList = gspDevTeamEnvRelationDao.findAll(example);

            for(GspDevTeamEnvRelation g:gspDevTeamEnvRelationList){
                urls.add(gspDevEnvMapDao.findById(g.getEnvId()).get().getDevUrl());
            }
        } catch (Exception e){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_ERROR_0003);
        }
        return urls;
    }

    private void addOneUser(SynchqronizationInfoDto synchqronizationInfoDto,String jsonObject,HttpHeaders headers){
        try{
            String address=ApiEnum.ADDUSER.getApiAddress(synchqronizationInfoDto.getTargetAddress());
            HttpEntity<String> requestEntity = new HttpEntity<>(jsonObject, headers);
            ResponseEntity<String> resultEntityParameter = restTemplate.postForEntity(address,requestEntity,String.class);
            addOneUserPosition(synchqronizationInfoDto);
            saveBuildResult(synchqronizationInfoDto, synchqronizationInfoDto.getUserId());
        } catch (Exception e){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_ERROR_0004);
        }
    }

    private void addOneUserPosition(SynchqronizationInfoDto synchqronizationInfoDto){
        try{
            List<Position> positionListAll = queryAllPosition(synchqronizationInfoDto);
            List<Position> positionList = new ArrayList<>();
            if(synchqronizationInfoDto.getIsAdmin()){
                Optional<Position> positionOptional = positionListAll.stream().filter(s ->s.getName().equals("管理员岗")).findFirst();
                positionList.add(positionOptional.get());
            } else {
                Optional<Position> positionOptional = positionListAll.stream().filter(s ->s.getName().equals("开发岗")).findFirst();
                positionList.add(positionOptional.get());
            }
            HttpHeaders headers= generateHeader(synchqronizationInfoDto.setTargetApi( ApiEnum.USERPOSITION.getName()));
            SysAssResultPackage sysAssResultPackage = combinePositionParameter(synchqronizationInfoDto.getUserId(), positionList);

            ObjectMapper mapper = new ObjectMapper();
            String value = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(sysAssResultPackage);
            HttpEntity<String> requestEntity = new HttpEntity<>(value, headers);
            ResponseEntity<String> resultEntityParameter = restTemplate.postForEntity(ApiEnum.USERPOSITION.getApiAddress(synchqronizationInfoDto.getTargetAddress())+"?subjectType=user&objectType=position",requestEntity,String.class);
        } catch (Exception e){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_ERROR_0005);
        }
    }

    private List<Position> queryAllPosition(SynchqronizationInfoDto synchqronizationInfoDto){
        HttpHeaders headers= generateHeader(synchqronizationInfoDto.setTargetApi(ApiEnum.POSITION.getName()));
        HttpEntity<String> requestEntity = new HttpEntity<>(headers);
        String url = ApiEnum.POSITION.getApiAddress(synchqronizationInfoDto.getTargetAddress());
        ResponseEntity<String> resultEntity = restTemplate.exchange(ApiEnum.POSITION.getApiAddress(synchqronizationInfoDto.getTargetAddress()), HttpMethod.GET,requestEntity,String.class);
        JSONArray jsonArray = JSON.parseObject(resultEntity.getBody()).getJSONArray("data");
        List<Position> positionList = jsonArray.toJavaList(Position.class);
        return positionList;
    }

    private SysAssResultPackage combinePositionParameter(String userid,List<Position> positionIds){
        SysAssResultPackage sysAssResultPackage =new SysAssResultPackage();
        sysAssResultPackage.setCheck(true);

        AuditEntity auditEntity =new AuditEntity();
        auditEntity.setId(userid);
        sysAssResultPackage.setOwnerAuditEntity(auditEntity);

        for(Position s: positionIds){
            AuditEntity auditEntityPosition =new AuditEntity();
            auditEntityPosition.setId(s.getId());
            auditEntityPosition.setCode(s.getCode());
            auditEntityPosition.setName(s.getName());
            sysAssResultPackage.getAddingEntity().add(auditEntityPosition);
            sysAssResultPackage.getAddingResults().add(s.getId());
        }

        sysAssResultPackage.setAllFlag("0");
        sysAssResultPackage.setOwnerId(userid);
        return sysAssResultPackage;
    }
    private Boolean verifyUserIsAppend(SynchqronizationInfoDto synchqronizationInfoDto){

        HttpHeaders headers= generateHeader(synchqronizationInfoDto.setTargetApi(ApiEnum.CHECKUSER.getName()));
        HttpEntity<String> requestEntity = new HttpEntity<>(headers);
        String url = ApiEnum.CHECKUSER.getApiAddress(synchqronizationInfoDto.getTargetAddress())+"?param={}";
        ResponseEntity<String> resultEntity = restTemplate.exchange(url, HttpMethod.GET,requestEntity,String.class);
        String str = resultEntity.getBody();
        if(str.indexOf(synchqronizationInfoDto.getUserId())>-1){
            return true;
        } else {
            return false;
        }

    }

    private Boolean verifyEnvironmentIsBind(SynchqronizationInfoDto synchqronizationInfoDto){
        HttpHeaders headers= generateHeader(synchqronizationInfoDto.setTargetApi(ApiEnum.CHECKENVIRONMENT.getName()));
        HttpEntity<String> requestEntity = new HttpEntity<>(headers);
        ResponseEntity<String> resultEntity = restTemplate.exchange(ApiEnum.CHECKENVIRONMENT.getApiAddress(synchqronizationInfoDto.getTargetAddress()), HttpMethod.GET,requestEntity,String.class);
        if(resultEntity.getBody().equals("exsis")){
            return true;
        } else {
            return false;
        }
    }
    private Boolean saveEnvironmentIsBind(SynchqronizationInfoDto synchqronizationInfoDto){
        HttpHeaders headers= generateHeader(synchqronizationInfoDto.setTargetApi(ApiEnum.SAVEENVIRONMENT.getName()));
        HttpEntity<String> requestEntity = new HttpEntity<>(headers);
        ResponseEntity<String> resultEntity = restTemplate.exchange(ApiEnum.SAVEENVIRONMENT.getApiAddress(synchqronizationInfoDto.getTargetAddress()), HttpMethod.GET,requestEntity,String.class);
        if(resultEntity.getBody().equals("exsis")){
            return true;
        } else {
            return false;
        }
    }

    private String getUserJsonString(String userId){
//        Optional <GetNexusUserPasswordRelation> optional = paasUserPasswordDao.findById(userId);
//        String password="Test6530?!##";
//        if(optional.isPresent()){
//            password =paasUserPasswordDao.findById(userId).get().getUserPassword();
//        }

        String value="";
        try{
            User user = userManager.getUser(userId);
            User userInfo=user.clone();
            userInfo.setSysOrgId("bc66aab4-8d3a-c47a-71a2-8fd7f9efc7a4");
            userInfo.setSysOrgName("所有");

//            userInfo.setRemark(password);
            userInfo.setCreatedTime(null);
            userInfo.setLastModifiedTime(null);
            userInfo.setLastLoginTime(null);
            for(GroupEntity ge: userInfo.getAssGroup()){
                ge.setCreatedTime(null);
                ge.setLastModifiedTime(null);
            }
            UserExtend userExtend = userExtendManager.getExtendByUserId(userId);
            userInfo.getUserExtend().setEmail(userExtend.getEmail());
            Map<String,String> map=new HashMap<>();
            map.put("zh-CHS","");
            userInfo.getUserNameLanguage().setMiddleName(map);

            ObjectMapper mapper = new ObjectMapper();
            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
            value = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(userInfo);
        } catch (Exception e){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_ERROR_0006);
        }
        return value;
    }

    private HttpHeaders generateHeader(SynchqronizationInfoDto synchqronizationInfoDto){
        getApikey(synchqronizationInfoDto);
        HttpHeaders headers = new HttpHeaders();
        try {
            Credentials credentials = Credentials.create(synchqronizationInfoDto.getApiKey(),synchqronizationInfoDto.getSecretKey());
            Signature build = Signature.builder(credentials, synchqronizationInfoDto.getTargetApi()).build();
            String auth= build.getAuthorization();
            headers.add("Authorization",auth);
            headers.add("X-ECC-Current-Tenant","10000");
            headers.add("Accept-Language","zh-CHS");
            headers.setContentType(MediaType.APPLICATION_JSON);
        } catch (Exception e){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_ERROR_0007);
        }
        return headers;
    }
    private void getApikey(SynchqronizationInfoDto synchqronizationInfoDto){
        try{
            Optional<GspDevEnvMap> gspDevEnvMapOptional = gspDevEnvMapDao.findAll().stream().filter(s -> s.getDevUrl().equals(synchqronizationInfoDto.getTargetAddress())).findFirst();
            synchqronizationInfoDto.setApiKey(gspDevEnvMapOptional.get().getApiKey());
            synchqronizationInfoDto.setSecretKey(gspDevEnvMapOptional.get().getSecretKey());
        }catch (Exception e){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_ERROR_0008);
        }
    }

    private int saveBuildResult(SynchqronizationInfoDto synchqronizationInfoDto,String userId) {
        try{
            GspPaasUserSynch paasUserSynch=new GspPaasUserSynch();
            paasUserSynch.setId(UUID.randomUUID().toString());
            paasUserSynch.setUserId(userId);
            paasUserSynch.setTeamId(synchqronizationInfoDto.getTeamId());
            paasUserSynch.setEnvironmentId(synchqronizationInfoDto.getTargetAddress());

            Timestamp time = Timestamp.valueOf(LocalDateTime.now());
            paasUserSynch.setCreateTime(time);

            User user=CommonUtils.findUserInfo();
            paasUserSynch.setCreateUserId(user.getId());

            synchronizationInfoDao.save(paasUserSynch);
        } catch (Exception e){
            throw new PaasException(ErrorCodes.ECP_PAASUSER_ERROR_0009);
        }
        return 1;
    }
}

